package com.jbp.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jbp.dao.GiftEventDao;
import com.jbp.exception.RRException;
import com.jbp.model.GiftEvent;
import com.jbp.redis.RedisConfigService;
import com.jbp.service.GiftEventService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import com.jbp.utils.PageUtils;
import com.jbp.utils.Query;

import java.io.Serializable;
import java.time.Duration;
import java.util.List;
import java.util.Map;

/**
 * 活动礼物(GiftEvent)表服务实现类
 * @author cc
 * @since 2020-12-25 12:26:38
 */
@Service
public class GiftEventServiceImpl extends ServiceImpl<GiftEventDao, GiftEvent> implements GiftEventService {
    @Autowired
    private RedisTemplate redisTemplate;

    public static final String eventLock = "event_lock";
    public static final String eventScorePrefix = "eventScore:";

    /** 活动逻辑
     1. 获取gift_event表，看是否有活动并且del=0
     2. redis加锁，所有活动同一个锁，锁超时时间5min，value为userId
     3. redis加活动总额，跟活动id关联
     4. 判断金额是否达到要求，没达到，释放锁
     5. 判断updateTime是否超过2分钟,避免重复发放
     6. 重置活动金额，重新开始累积
     7. 更新gift_event表，判断times是否与查询一致，如果不一致说明发放过，抛异常
     8. 发放礼物，校验redis锁value，释放锁
     */

    @Override
    public List<GiftEvent> goingEvent(){
       return list(new QueryWrapper<GiftEvent>()
               .eq("del", 0));
    }

    /**加锁*/
    @Override
    public boolean lock(Integer userId) {
        try {
            ValueOperations<Serializable, Object> operations= redisTemplate.opsForValue();
            return operations.setIfAbsent(eventLock,userId, Duration.ofMinutes(5));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**释放锁*/
    @Override
    public void unLock(Integer userId) {
        ValueOperations<Serializable, Object> operations= redisTemplate.opsForValue();
        Object o = operations.get(eventLock);
        if (o==null || !o.equals(userId)) {
            throw new RRException("网络异常");
        } else {
            redisTemplate.delete(eventLock);
        }
    }

    /**取积分*/
    @Override
    public Integer getScore(Integer eventId) {
        try {
            ValueOperations<Serializable, Object> operations= redisTemplate.opsForValue();
            Integer score = (Integer) operations.get(eventScorePrefix + eventId);
            return score==null ? 0 : score;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**设置积分*/
    @Override
    public void setScore(Integer eventId, Integer score) {
        try {
            ValueOperations<Serializable, Object> operations= redisTemplate.opsForValue();
            operations.set(eventScorePrefix+eventId, score);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void addTimes(GiftEvent giftEvent) {
        Integer result = getBaseMapper().addTimesWithLock(giftEvent);
        if (null == result || result < 1) {
            throw new RRException("服务器忙");
        }
    }

}